from logging import getLogger
import os
from os.path import join, isdir, exists, dirname
import re
from shutil import rmtree, copy2

import zc.recipe.egg


class Recipe(object):
    def __init__(self, buildout, name, options):
        self.buildout = buildout
        self.name = name
        self.options = options
        self._log = getLogger(self.name)
        
        self.options.setdefault('directory',
                                join(buildout['buildout']['parts-directory'],
                                     self.name))
        
        self.options.setdefault('conf-directory',
                                join(self.options['directory'],'conf'))
        
        self.options.setdefault('template-directory',
                                join(dirname(__file__),'template'))
        
        self.options.setdefault('logging-prefix',self.name)
        
        self.options.setdefault('port','8085')
        self.options.setdefault('pid-file',
                                join(self.options['directory'],'var',
                                     '%s.pid' % (self.name,)))
        self.options.setdefault('uid','')
        self.options.setdefault('gid','')
        
        self.scripts = zc.recipe.egg.Scripts(buildout, name, options)
        
    
    def install(self):
        self.create_directories()
        self.build_includes()
        self.install_script()
        return ()
        
    
    def update(self):
        self.build_includes()
        self.install_script()
        return ()
    
    def install_script(self):
        options = self.scripts.options
        options['entry-points'] = '%s=meercat.server.nevow.runner:run_with_options' % (self.name,)
        
        arguments = []
        
        if self.options['uid']:
            arguments.append('--uid=%s' % (self.options['uid'],))
        
        if self.options['gid']:
            arguments.append('--gid=%s' % (self.options['gid'],))
        
        arguments.append('--prefix=%s' % (self.options['logging-prefix'],))
        arguments.append('--pidfile=%s' % (self.options['pid-file'],))
        
        arguments.append('meercat-nevow')
        arguments.append('--zcml=%s' % (join(self.options['conf-directory'],'site.zcml'),))
        arguments.append('--port=%s' % (str(self.options['port']),))
        
        if self.options.get('logging-config',None):
            arguments.append('--logconfig=%s' % (str(self.options['logging-config']),))
        
        options['arguments'] = str(arguments)
        self.scripts.install()
    
    def create_directories(self):
        if not isdir(self.options['directory']):
            os.mkdir(self.options['directory'])
        
        if not isdir(self.options['conf-directory']):
            os.mkdir(self.options['conf-directory'])
        
        if not isdir(join(self.options['directory'],'var')):
            os.mkdir(join(self.options['directory'],'var'))
            
    
    def build_includes(self):
        location = join(self.options['conf-directory'],'includes')
        
        if exists(location):
            rmtree(location)
        
        os.mkdir(location)
        
        copy2(join(self.options['template-directory'],'site.zcml'),
              join(self.options['conf-directory'], 'site.zcml'))
        
        zcml = self.options.get('zcml','').split()
        
        n = 0
        if zcml and len(zcml):
            package_match = re.compile('[\w\d]+([.][\w\d]+)*$').match
            for package in zcml:
                n += 1
                original = package
                if ':' in package:
                    package, filename = package.split(':')
                else:
                    filename = None
                
                if '-' in package:
                    package, type = package.split('-')
                    if type not in ('configure','meta','overrides'):
                        raise ValueError('Invalid zcml type', original)
                else:
                    type = 'configure'
                
                if filename is None:
                    filename = type + '.zcml'
                
                if not package_match(package):
                    raise ValueError('Invalid package name', original)
                
                open(join(location,
                          "%3.3d-%s-%s.zcml" % (n, package, type),),
                    'w').write('<include package="%s" file="%s" />\n' % (package,
                                                                         filename))
        extra_zcml = self.options.get('extra-zcml','').split()
        if extra_zcml and len(extra_zcml):
            for filename in extra_zcml:
                if filename:
                    n += 1
                    if not exists(filename):
                        raise ValueError('Extra zcml file does not exist: %s' % (filename,))
                    open(join(location,
                              '%3.3d-%s-extra.zcml' % (n, filename.replace('/','_'),)),
                         'w').write('<include file="%s" />\n' % (filename,))
